﻿using System;
using System.Collections.Generic;
using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace IotS.Core.Helpers
{
    public class QueueSub : IDisposable
    {
        private readonly IConnection _connection;
        private readonly IModel _channel;
        private readonly bool _receive = false;

        public QueueSub(bool receive = false)
        {
            _receive = receive;
            var factory = new ConnectionFactory
            {
                HostName = ConfigHelper.Settings.RabbitMQ.Host,
                UserName = ConfigHelper.Settings.RabbitMQ.UserName,
                Password = ConfigHelper.Settings.RabbitMQ.Password,
                AutomaticRecoveryEnabled = true
            };

            _connection = factory.CreateConnection();
            _channel = _connection.CreateModel();

            var exchangeName = receive
                ? ConfigHelper.Settings.RabbitMQ.ExchangeName
                : ConfigHelper.Settings.RabbitMQ.SubExchangeName;
            var queueName = receive
                ? ConfigHelper.Settings.RabbitMQ.QueueName
                : ConfigHelper.Settings.RabbitMQ.SubQueueName;

            _channel.ExchangeDeclare(exchangeName, ExchangeType.Fanout);
            _channel.QueueDeclare(queueName, true, false, true, null);
            _channel.QueueBind(queueName, exchangeName, "");
            _channel.BasicQos(0, 1, false);
        }

        public void Start(Action<string> received)
        {
            var consumer = new EventingBasicConsumer(_channel);

            consumer.Received += (s, e) =>
            {
                var body = e.Body;
                var message = Encoding.UTF8.GetString(body);
                received(message);

                _channel.BasicAck(e.DeliveryTag, false);
            };
            var queueName = _receive
                ? ConfigHelper.Settings.RabbitMQ.QueueName
                : ConfigHelper.Settings.RabbitMQ.SubQueueName;

            _channel.BasicConsume(queueName, false, consumer);
        }

        public void Dispose()
        {
            _connection?.Dispose();
            _channel?.Dispose();
        }
    }
}
